import type { MirrorWebsiteFile } from "@common/spider-types.ts";
import * as cheerio from "cheerio";
import fetch from "node-fetch";
import { type Element } from "domhandler";

/**
 * 抓取镜像网站,解析出文件/文件夹列表(支持大多数镜像网站)
 * @param url 镜像地址
 */
export async function getMirrorFiles(url: string): Promise<MirrorWebsiteFile[]> {
  const resp = await fetch(url);
  const html = await resp.text();

  const $ = cheerio.load(html);
  let fileList: MirrorWebsiteFile[];
  if (url.includes("mirrors.aliyun.com")) {
    // 阿里云镜像
    fileList = parseAliyun($);
  } else if (url.includes("dlcdn.apache.org") || url.includes("mirrors.tuna.tsinghua.edu.cn/apache")) {
    // Apache和清华大学apache
    fileList = parse0($);
  } else if (url.includes("mirrors.tuna.tsinghua.edu.cn")) {
    // 清华大学
    fileList = parseTsinghua($);
  } else if (url.includes("mirrors.nju.edu.cn")) {
    // 南京大学
    fileList = parseNanjingu($);
  } else if (url.includes("mirrors.neusoft.edu.cn")) {
    // 大连东软信息学院
    fileList = parseNeusoft($);
  } else if (url.includes("mirror.nyist.edu.cn")) {
    // 南阳理工学院
    fileList = parseNyist($);
  } else {
    // 华为云和腾讯云，以及其他镜像站点
    fileList = parse1($);
  }
  return fileList;
}

/**
 * 解析Apache和清华大学的镜像
 * @param $
 */
function parse0($: cheerio.CheerioAPI): MirrorWebsiteFile[] {
  const fileList: MirrorWebsiteFile[] = [];

  const content = $("pre").text();
  // console.log(content);
  const lines = content.split(/[\r\n]/).slice(1); // 跳过第一行,第一行是表头
  for (const it of lines) {
    const line = it.trim();
    if (!line || line.includes("Parent Directory")) {
      continue;
    }

    fileList.push(parseFileInfo(line));
  }

  return fileList;
}

/**
 * 解析华为云和腾讯云的镜像
 * @param $
 */
function parse1($: cheerio.CheerioAPI): MirrorWebsiteFile[] {
  const content = $("pre").last().text();
  const fileList: MirrorWebsiteFile[] = [];
  const lines = content.split(/[\r\n]/);
  for (const it of lines) {
    const line = it.trim();
    if (!line || line === "../") continue;

    fileList.push(parseFileInfo(line));
  }

  return fileList;
}

/**
 * 解析Apache和清华大学,腾讯云和华为云的一行文件信息
 * @param line
 */
function parseFileInfo(line: string): MirrorWebsiteFile {
  const [name, date0, time0, ...sizeTokens] = line.split(/\s+/);
  const date = new Date(date0 + " " + time0);
  const size = sizeTokens.join("");
  return {
    name: name.replace(/\/$/, ""),
    type: name.endsWith("/") ? "dir" : "file",
    date: date.toLocaleString(),
    size: size === "-" ? undefined : size,
  };
}

/**
 * 解析阿里云的镜像
 * @param $
 */
function parseAliyun($: cheerio.CheerioAPI): MirrorWebsiteFile[] {
  const table = $(".mirror-content .mirror-left .table");
  const tableRows = table.find("tbody tr");
  return parseTableFiles($, tableRows);
}

/**
 * 解析南京大学的镜像
 * @param $
 */
function parseNanjingu($: cheerio.CheerioAPI): MirrorWebsiteFile[] {
  const table = $("table#list");
  const tableRows = table.find("tbody tr");
  return parseTableFiles($, tableRows);
}

/**
 * 解析清华大学的镜像
 * @param $
 */
function parseTsinghua($: cheerio.CheerioAPI): MirrorWebsiteFile[] {
  const table = $("table#list");
  const tableRows = table.find("tbody tr");
  return parseTableFiles($, tableRows);
}

/**
 * 解析大连东软信息学院的镜像
 * @param $
 */
function parseNeusoft($: cheerio.CheerioAPI): MirrorWebsiteFile[] {
  const table = $("table#list");
  const tableRows = table.find("tbody tr");
  return parseTableFiles($, tableRows);
}

/**
 * 解析南洋理工信息学院的镜像
 * @param $
 */
function parseNyist($: cheerio.CheerioAPI): MirrorWebsiteFile[] {
  const table = $("table#list");
  const tableRows = table.find("tbody tr");
  return parseTableFiles($, tableRows);
}

/**
 * 解析表格文件,支持阿里云和南京大学清华的网站
 * @param $
 * @param tableRows
 */
function parseTableFiles($: cheerio.CheerioAPI, tableRows: cheerio.Cheerio<Element>) {
  const fileList: MirrorWebsiteFile[] = [];
  tableRows.each((_, tr) => {
    const $this = $(tr);
    const $a = $this.find(".link a");
    if ($a.attr("href") === "../") return;
    const item = $a.text().trim();
    if (!item) return;

    const type = item.endsWith("/") ? "dir" : "file";
    const name = item.replace(/\/$/, "");

    const size = $this.find(".size").text().trim();
    const date = $this.find(".date").text().trim();
    fileList.push({ name, type, date, size: size === "-" ? undefined : size });
  });

  return fileList;
}
